﻿// ParseLib - An open source library for natural language processing.
// Copyright (C) Kais Dukes, 2012. E-mail: kais@kaisdukes.com
// http://parselib.org

using System;
using log4net;
using ParseLib.Corpora;
using ParseLib.Text;

namespace ParseLib.Experiments
{
    public class CrossValidation : EvaluationMethod
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof (CrossValidation));

        public int FoldCount { get; set; }

        public int Iterations { get; set; }

        public override void Evaluate(IModel model, ICorpus corpus)
        {
            // Diagnostics.
            Log.DebugFormat("Performing cross validation using {0} folds...", FoldCount);

            // Work out how many iterations to run.
            var runCount = Iterations == 0 ? FoldCount : Iterations;

            // Partition the corpus.
            var aggregatedMetric = CreateMetric();
            for (var i = 1; i <= runCount; i++)
            {
                Log.DebugFormat("Cross validation: {0} / {1}...", i, FoldCount);
                var partition = new CorpusPartition(i, FoldCount, corpus);

                // Train the model using training data.
                Log.DebugFormat("Training {0}...", DisplayName.Of(model));
                model.Train(partition.TrainingData);

                // Evaluate the model using test data.
                Log.Debug("Evaluating...");
                EvaluationMetric.Evaluate(model, partition.TestData);
                Log.Debug(EvaluationMetric);

                // Aggregate.
                aggregatedMetric.Add(EvaluationMetric);
            }

            // Add the results.
            Log.Debug("*** RESULTS ***");
            Log.Debug(aggregatedMetric);
        }

        private IEvaluationMetric CreateMetric()
        {
            return (IEvaluationMetric) Activator.CreateInstance(EvaluationMetric.GetType());
        }
    }
}